<template>
  <div class="">
    <div class="search-box clearfix" v-if="itemsConfig.search && showSearchForm">
      <div class="fr" v-if="showSearchForm">
        <el-button class="btn-main" size="small" @click="search">搜索</el-button>
        <el-button class="btn-default" size="small" @click="reset">重置</el-button>
        <el-button v-if="state.seniorBtn" class="btn-default" size="small" @click="toggle">高级搜索</el-button>
      </div>
      <el-form ref="searchFormRef" :class="state.fold ? 'fold' : ''" v-if="showSearchForm" :model="state.searchForm" :label-width="formLabelWidth" :inline="true">
        <span v-for="(item, index) in itemsConfig.search" :key="index">
          <el-form-item :label="item.label">
            <template v-if="item.type === 'input'">
              <el-input v-model="state.searchForm[item.prop]" :placeholder="item.placeholder" class="w190" :style="item.style" clearable></el-input>
            </template>
            <template v-if="item.type === 'input-between'">
              <el-input v-model.trim="state.searchForm[item.props[0]]" :placeholder="item.placeholder" class="w90" clearable></el-input>
              -
              <el-input v-model.trim="state.searchForm[item.props[1]]" :placeholder="item.placeholder" class="w90" clearable></el-input>
            </template>
            <template v-if="item.type === 'select'">
              <el-select v-model.trim="state.searchForm[item.prop]" :filterable="item.filterable" :multiple="item.multiple" :collapse-tags="item.multiple" :placeholder="item.placeholder" class="w190" :style="item.style" :clearable="item.clearable === undefined || item.clearable">
                <el-option v-for="option in item.options" :key="option.id" :label="option.value" :value="option.code"></el-option>
              </el-select>
            </template>
            <template v-if="item.type === 'datetime-between'">
              <el-popover placement="bottom" trigger="hover" width="260">
                <div class="flex">
                  <el-button size="small" @click="quickTime(item.props, 0, 'datetime')">昨日</el-button>
                  <el-button size="small" @click="quickTime(item.props, 1, 'datetime')">今天</el-button>
                  <el-button size="small" @click="quickTime(item.props, 2, 'datetime')">本周</el-button>
                  <el-button size="small" @click="quickTime(item.props, 3, 'datetime')">本月</el-button>
                </div>
                <template #reference>
                  <span>
                    <el-date-picker v-model="state.searchForm[item.props[0]]" style="width: 190px" type="datetime" placeholder="选择日期" value-format="YYYY-MM-DD HH:mm:ss" @change="checkInvalid(item.props, item.props[0])"></el-date-picker>
                    -
                    <el-date-picker v-model="state.searchForm[item.props[1]]" style="width: 190px" type="datetime" placeholder="选择日期" value-format="YYYY-MM-DD HH:mm:ss" @change="checkInvalid(item.props, item.props[1])"></el-date-picker>
                  </span>
                </template>
              </el-popover>
            </template>
            <template v-if="item.type === 'date-between'">
              <el-popover placement="bottom" trigger="hover" width="260">
                <div class="flex">
                  <el-button size="small" @click="quickTime(item.props, 0, 'date')">昨日</el-button>
                  <el-button size="small" @click="quickTime(item.props, 1, 'date')">今天</el-button>
                  <el-button size="small" @click="quickTime(item.props, 2, 'date')">本周</el-button>
                  <el-button size="small" @click="quickTime(item.props, 3, 'date')">本月</el-button>
                </div>
                <template #reference>
                  <span>
                    <el-date-picker v-model="state.searchForm[item.props[0]]" style="width: 190px" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" @change="checkInvalid(item.props, item.props[0])"></el-date-picker>
                    -
                    <el-date-picker v-model="state.searchForm[item.props[1]]" style="width: 190px" type="date" placeholder="选择日期" value-format="YYYY-MM-DD" @change="checkInvalid(item.props, item.props[0])"></el-date-picker>
                  </span>
                </template>
              </el-popover>
            </template>
            <template v-if="item.type === 'datetime'">
              <el-date-picker v-model="state.searchForm[item.prop]" style="width: 190px" type="datetime" placeholder="选择日期" value-format="YYYY-MM-DD HH:mm:ss"></el-date-picker>
            </template>
            <template v-if="item.type === 'date'">
              <el-date-picker v-model="state.searchForm[item.prop]" style="width: 190px" type="date" placeholder="选择日期" value-format="YYYY-MM-DD"></el-date-picker>
            </template>
            <template v-if="item.type === 'searchSlot'">
              <slot name="searchSlot" :searchForm="state.searchForm" :itemProp="item.prop"></slot>
            </template>
          </el-form-item>
        </span>
      </el-form>
    </div>
    <div class="handle-box f14">
      <slot name="handle"></slot>
    </div>
    <div class="rel">
      <el-table ref="multipleTableRef" :data="state.table.list" :height="`${state.myHeight}px`" stripe :border="true" v-loading="state.table.loading" size="small" class="table-normal f16" @selection-change="selectionHandle" @sort-change="sortChange" :row-key="getRowKey" :row-height="60">
        <el-table-column v-if="itemsConfig.table.selection" :reserve-selection="true" type="selection" width="55"></el-table-column>
        <el-table-column v-if="itemsConfig.table.index" type="index" label="序号" width="55"></el-table-column>
        <template v-for="item in itemsConfig.table.columns">
          <el-table-column v-if="item.dicCode && !item.hide" :key="item.prop" :label="item.label" :prop="item.prop" :width="item.width" :sortable="item.sortable" :resizable="item.resizable" :align="item.align">
            <template #default="scope">
              <el-popover v-if="item.tooltip" popper-class="searchPop" placement="top" title="" width="300" trigger="hover" :content="$utils.getValue(item.dicCode, scope.row[item.prop])">
                <template #reference>
                  <span :class="{ ellipsis: item.ellipsis !== false }">
                    {{ $utils.getValue(item.dicCode, scope.row[item.prop]) }}
                  </span>
                </template>
              </el-popover>
              <span v-else :class="{ ellipsis: item.ellipsis !== false }">
                {{ $utils.getValue(item.dicCode, scope.row[item.prop]) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column v-if="item.myslot && !item.hide" :label="item.label" :key="item.prop" :width="item.width" :sortable="item.sortable" :show-overflow-tooltip="item.tooltip" :resizable="item.resizable" :align="item.align">
            <template #default="scope">
              <el-popover v-if="item.tooltip" popper-class="searchPop" placement="top" title="" width="300" trigger="hover" :content="scope.row[item.prop]">
                <template #reference>
                  <span :class="{ ellipsis: item.ellipsis !== false }">
                    <slot :name="item.prop" :row="scope.row" :index="scope.$index"></slot>
                  </span>
                </template>
              </el-popover>
              <slot v-else :name="item.prop" :row="scope.row" :index="scope.$index" :class="{ ellipsis: item.ellipsis !== false }"></slot>
            </template>
          </el-table-column>
          <el-table-column v-if="!item.dicCode && !item.myslot && !item.hide" v-bind="item" :label="item.label" :key="item.prop" :prop="item.prop" :width="item.width" :sortable="item.sortable" :resizable="item.resizable" :align="item.align">
            <template #default="scope">
              <el-popover v-if="item.tooltip" popper-class="searchPop" placement="top" title="" width="300" trigger="hover" :content="scope.row[item.prop]">
                <template #reference>
                  <span :class="{ ellipsis: item.ellipsis !== false }">
                    {{ scope.row[item.prop] }}
                  </span>
                </template>
              </el-popover>
              <span v-else :class="{ ellipsis: item.ellipsis !== false }">{{ scope.row[item.prop] }}</span>
            </template>
          </el-table-column>
        </template>
        <template v-if="itemsConfig.table.columnHandle">
          <el-table-column label="操作" :width="itemsConfig.table.columnWidth" :fixed="itemsConfig.table.columnHandleFixed">
            <template #default="scope">
              <slot name="columnHandle" :row="scope.row" :index="scope.$index"></slot>
            </template>
          </el-table-column>
        </template>
      </el-table>
      
      <div class="page-normal mt5 tr bg-white flex" style="justify-content: flex-end">
        <template v-if="state.pagination.total === null">
          <el-link :disabled="state.pagination.pager[props.pageKey] === 1" :underline="false" class="mr10" @click="prevClick">上一页</el-link>
          <el-link :disabled="state.table.list.length < state.pagination.pager[props.pageSizeKey]" :underline="false" class="mr10" @click="nextClick">下一页</el-link>
          <!-- searchCount为false存在返回total为null或者0的情况 -->
          <el-button size="small" v-loading="state.table.loading" @click="getTotal">查询总数</el-button>
        </template>

        <template v-else>
        <el-pagination
          v-model:current-page="state.pagination.pager[props.pageKey]"
          v-model:page-size="state.pagination.pager[props.pageSizeKey]"
          :page-sizes="[20, 50, 100]"
          :page-size="50"
          layout="total, sizes, prev, pager, next"
          :pager-count="5"
          :total="state.pagination.total" />
        </template>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted, onBeforeMount, nextTick } from 'vue';
import config from "./config.js";
import dayjs from 'dayjs';
import { useAppStore } from '@/store/modules/app';
import { ElMessage } from 'element-plus'
// import Pager from '@/components/pager/Pager.vue'

const props = defineProps({
  autoRun: { type: Boolean, default: true },
  showSearchForm: { type: Boolean, default: true },
  sttKey: { type: String, default: "empty" },
  sttConfig: { type: Object, default: null },
  formLabelWidth: { type: String, default: "90px" },
  selectedItems: { type: Array, default: () => [] },
  tableListApi: { type: Function, default: null },
  tableHeight: { type: [Number, String], default: 0 },
  extraParams: { type: Object, default: () => ({}) },
  pageKey: { type: String, default: "pageNum" },
  pageSizeKey: { type: String, default: "pageSize" },
  searchCountKey: { type: String, default: '' }
});

const emit = defineEmits([
  'search',
  'reset',
  'data',
  'update:selectionItems',
  'getSelectionItems',
  'sortChange'
]);

const searchFormRef = ref(null);
const multipleTableRef = ref(null);
const appStore = useAppStore();

const state = reactive({
  myHeight: 400,
  searchForm: {},
  seniorBtn: false,
  fold: false,
  table: {
    loading: false,
    list: [],
  },
  selections: [],
  selectedOptions: [],
  pagination: {
    isSearchCount: false,
    total: null,
    pager: {
      [props.pageKey]: 1,
      [props.pageSizeKey]: 100,
    },
  },
});

// 用来存放初始化的默认值
const defaultValueItems = reactive({});

const itemsConfig = computed(() => {
  return props.sttConfig || config[props.sttKey] || config["empty"];
});

onBeforeMount(() => {
  initSearchItems();
});

onMounted(() => {
  const searchHeight = searchFormRef.value.$el.offsetHeight
  if(searchHeight > 50) {
    state.seniorBtn = true
    state.fold = true
    computedMyTableHeight()
  } else {
    state.seniorBtn = false
    state.fold = false
  }
  if (props.autoRun) {
    search();
  }
});

const toggle = () => {
  state.fold = !state.fold;
  nextTick(() => {
    computedMyTableHeight()
  })
}

const computedMyTableHeight = () => {
  if (props.tableHeight) {
    state.myHeight = props.tableHeight
  } else {
    if(state.fold) {
      return appStore.windowHeight - 250;
    } else {
      return appStore.windowHeight - searchFormRef.value.$el.offsetHeight - 350;
    }
  }
}

const showSelection = (array) => {
  if (multipleTableRef.value && array && array.length > 0) {
    array.forEach(item => {
      state.table.list.forEach(val => {
        if (val.id === item.id) {
          multipleTableRef.value.toggleRowSelection(val, true);
        }
      });
    });
  }
};

const getRowKey = (row) => {
  return row.id;
};

const initSearchItems = () => {
  if (itemsConfig.value.search) {
    itemsConfig.value.search.forEach(item => {
      if (item.prop && item.prop.id) {
        state.searchForm[item.prop.id] = undefined;
        state.searchForm[item.prop.name] = undefined;
      } else if (Array.isArray(item.props)) {
        state.searchForm[item.props[0]] = undefined;
        state.searchForm[item.props[1]] = undefined;
      } else {
        state.searchForm[item.prop] = undefined;
        if (item.propName) {
          state.searchForm[item.propName] = undefined;
        }
      }

      if (item.defaultValue) {
        state.searchForm[item.prop] = item.defaultValue;
        defaultValueItems[item.prop] = item.defaultValue;
      }
      if (item.defaultValueIndexAndKey) {
        state.searchForm[item.prop] = item.options[item.defaultValueIndexAndKey[0]][item.defaultValueIndexAndKey[1]];
        defaultValueItems[item.prop] = item.options[item.defaultValueIndexAndKey[0]][item.defaultValueIndexAndKey[1]];
      }
    });
  }
};

const search = () => {
  emit('search');
  state.pagination.pager[props.pageKey] = 1;
  getTableList();
};

const reset = () => {
  Object.keys(state.searchForm).forEach(key => {
    state.searchForm[key] = defaultValueItems[key];
  });
  if (multipleTableRef.value) {
    multipleTableRef.value.clearSelection();
  }
  emit('reset');
};

const getTableList = () => {
  state.table.loading = true;
  if (props.tableListApi) {
    const params = {
      ...props.extraParams,
      ...state.searchForm,
      ...state.pagination.pager,
    }
    if(props.searchCountKey) {
      params[props.searchCountKey] = state.pagination.isSearchCount
    }
    props.tableListApi(params).then(res => {
      if (res.code === 0 || res.code === 1) {
        const { records, list, total } = res.data || res.result;
        state.table.list = records || list || (Array.isArray(res.data) && res.data) || res.data.data || [];
        if(props.searchCountKey) {
          state.pagination.total = state.pagination.isSearchCount ? total : null
        } else {
          state.pagination.total = total
        }
        emit('data', res.data);
      } else {
        ElMessage.error((res && res.desc) || "stt提示: 接口有问题");
      }
    }).finally(() => {
      state.table.loading = false;
      showSelection(state.selectedOptions);
    })
  }
};

const getTotal = () => {
  state.pagination.isSearchCount = true;
  getTableList();
};


watch(() => state.pagination.pager[props.pageKey], (newPage) => {
  handleCurrentChange(newPage)
});

watch(() => state.pagination.pager[props.pageSizeKey], (newSize) => {
  handleSizeChange(newSize)
});

const handleCurrentChange = (page) => {
  state.pagination.pager[props.pageKey] = page;
  getTableList();
};

const handleSizeChange = (size) => {
  state.pagination.pager[props.pageSizeKey] = size;
  getTableList();
};

const prevClick = () => {
  state.pagination.pager[props.pageKey] = --state.pagination.pager[props.pageKey];
};

const nextClick = () => {
  state.pagination.pager[props.pageKey] = ++state.pagination.pager[props.pageKey];
};

watch(() => props.selectedItems, (newVal) => {
  state.selectedOptions = newVal;
  showSelection(newVal);
}, { deep: true });

const selectionHandle = (items) => {
  state.selections = items;
  emit('update:selectionItems', items);
  emit('getSelectionItems', items);
};

const sortChange = (params) => {
  emit('sortChange', params);
};

const quickTime = (props, type, formatType) => {
  if (type === 0) {
    state.searchForm[props[0]] = dayjs().subtract(1, "day").format(`YYYY-MM-DD${formatType === "datetime" ? " 00:00:00" : ""}`);
    state.searchForm[props[1]] = dayjs().subtract(1, "day").format(`YYYY-MM-DD${formatType === "datetime" ? " 23:59:59" : ""}`);
  } else if (type === 1) {
    state.searchForm[props[0]] = dayjs().format(`YYYY-MM-DD${formatType === "datetime" ? " 00:00:00" : ""}`);
    state.searchForm[props[1]] = dayjs().format(`YYYY-MM-DD${formatType === "datetime" ? " 23:59:59" : ""}`);
  } else if (type === 2) {
    state.searchForm[props[0]] = dayjs().day(1).format(`YYYY-MM-DD${formatType === "datetime" ? " 00:00:00" : ""}`);
    state.searchForm[props[1]] = dayjs().day(1).add(6, "day").format(`YYYY-MM-DD${formatType === "datetime" ? " 23:59:59" : ""}`);
  } else {
    state.searchForm[props[0]] = dayjs().startOf("month").format(`YYYY-MM-DD${formatType === "datetime" ? " 00:00:00" : ""}`);
    state.searchForm[props[1]] = dayjs().endOf("month").format(`YYYY-MM-DD${formatType === "datetime" ? " 23:59:59" : ""}`);
  }
};

const checkInvalid = (props, prop) => {
  if (dayjs(state.searchForm[props[0]]) > dayjs(state.searchForm[props[1]])) {
    ElMessage.warning("开始时间应小于结束时间");
    state.searchForm[prop] = "";
  }
};
</script>

<style lang="scss" scoped>
.colums-plus {
  position: absolute;
  z-index: 10;
  right: 10px;
  top: 10px;
  font-size: 20px;
  cursor: pointer;
}

.searchPop {
  width: 500px !important;
  font-size: 18px;
}

.el-table__body {
  width: 100%;
  table-layout: fixed !important;
}

::v-deep .el-table__body {
  width: 100%;
  table-layout: fixed !important;
}
</style>    